const mongoose = require('mongoose');
const validator = require('validator');
const bcrypt = require('bcryptjs');
const { roles } = require('../config/roles');
const { rolePermissions } = require('../config/permissions');

const userSchema = mongoose.Schema(
  {
    name: {
      type: String,
      trim: true,
    },
    nickname: {
      type: String,
      trim: true,
    },
    avatar: {
      type: String,
      trim: true,
    },
    email: {
      type: String,
      unique: true,
      sparse: true,  // 允许为null时的唯一索引
      trim: true,
      lowercase: true,
      validate(value) {
        if (value && !validator.isEmail(value)) {
          throw new Error('无效的电子邮件');
        }
      },
    },
    password: {
      type: String,
      trim: true,
      minlength: 8,
      validate(value) {
        if (value && (!value.match(/\d/) || !value.match(/[a-zA-Z]/))) {
          throw new Error('密码必须包含至少一个字母和一个数字');
        }
      },
      private: true, // 在JSON转换过程中不包含此字段
    },
    wechatOpenid: {
      type: String,
      unique: true,
      sparse: true,  // 允许为null时的唯一索引
    },
    role: {
      type: String,
      enum: roles,
      default: 'user',
    },
    permissions: {
      type: [String],
      default: [],
      select: false, // 默认不返回权限字段
    },
    isEmailVerified: {
      type: Boolean,
      default: false,
    },
    // 健康相关信息
    gender: {
      type: Number,
      enum: [0, 1, 2],  // 0-未知，1-男，2-女
      default: 0
    },
    height: {
      type: Number,
      min: 0,
      max: 300,  // 合理的身高范围（cm）
    },
    weight: {
      type: Number,
      min: 0,
      max: 500,  // 合理的体重范围（kg）
    },
    age: {
      type: Number,
      min: 0,
      max: 150,  // 合理的年龄范围
    },
    activityLevel: {
      type: Number,
      enum: [1, 2, 3, 4, 5],  // 1-久坐, 2-轻度活动, 3-中度活动, 4-高度活动, 5-极高活动
      default: 1
    },
    goal: {
      type: String,
      enum: ['减脂', '增肌', '健康饮食'],
      default: '健康饮食'
    },
    dailyCalorieGoal: {
      type: Number,
      min: 0,
    },
    lastLoginAt: {
      type: Date,
      default: Date.now
    },
    isActive: {
      type: Boolean,
      default: true
    },
    isDeleted: {
      type: Boolean,
      default: false
    }
  },
  {
    timestamps: true,
  }
);

// 排除私有字段
userSchema.methods.toJSON = function () {
  const user = this;
  const userObject = user.toObject();

  delete userObject.password;
  delete userObject.wechatOpenid;  // 不返回微信openid

  return userObject;
};

/**
 * 检查邮箱是否已被使用
 * @param {string} email - 电子邮件
 * @param {ObjectId} [excludeUserId] - 排除的用户ID
 * @returns {Promise<boolean>}
 */
userSchema.statics.isEmailTaken = async function (email, excludeUserId) {
  const user = await this.findOne({ email, _id: { $ne: excludeUserId } });
  return !!user;
};

/**
 * 验证密码是否匹配
 * @param {string} password - 密码
 * @returns {Promise<boolean>}
 */
userSchema.methods.isPasswordMatch = async function (password) {
  const user = this;
  return bcrypt.compare(password, user.password);
};

// 保存前加密密码
userSchema.pre('save', async function (next) {
  const user = this;
  if (user.isModified('password') && user.password) {
    user.password = await bcrypt.hash(user.password, 8);
  }
  next();
});

/**
 * 根据用户角色设置默认权限
 */
userSchema.methods.setDefaultPermissions = async function() {
  const user = this;
  user.permissions = rolePermissions[user.role] || [];
  await user.save();
};

/**
 * 添加权限
 * @param {string|string[]} permissions - 要添加的权限
 */
userSchema.methods.addPermissions = async function(permissions) {
  const user = this;
  const permissionsToAdd = Array.isArray(permissions) ? permissions : [permissions];
  
  // 过滤掉已有的权限
  const newPermissions = permissionsToAdd.filter(p => !user.permissions.includes(p));
  
  if (newPermissions.length > 0) {
    user.permissions.push(...newPermissions);
    await user.save();
  }
};

/**
 * 移除权限
 * @param {string|string[]} permissions - 要移除的权限
 */
userSchema.methods.removePermissions = async function(permissions) {
  const user = this;
  const permissionsToRemove = Array.isArray(permissions) ? permissions : [permissions];
  
  user.permissions = user.permissions.filter(p => !permissionsToRemove.includes(p));
  await user.save();
};

/**
 * @typedef User
 */
const User = mongoose.model('User', userSchema);

module.exports = User; 